#pragma once

#include <MCF/Code/StdMCF.hpp>
#include <MCF/Code/ModelessDialogClass.hpp>
#include <MCF/Code/TabControlClass.hpp>
#include <map>
#include <forward_list>
#include <list>
#include "VGAClass.hpp"
#include "KeyboardClass.hpp"
#include "BuzzerClass.hpp"

class MainDialogClass sealed : public MCF::ModelessDialogClass {
private:
	class _LockedWindowClass;
private:
	enum : UINT_PTR {
		_TIMER_GUILOCKED = 1
	};
private:
	static bool _EventGUIQueueMessageBoxProc(std::intptr_t nContext, std::intptr_t nArg1, std::intptr_t nArg2, std::intptr_t nArg3);

	static bool _ThreadEventGUISwitchToTabProc(std::intptr_t nContext, std::intptr_t nArg1, std::intptr_t nArg2, std::intptr_t nArg3);
	static bool _ThreadEventGUILockProc(std::intptr_t nContext, std::intptr_t nArg1, std::intptr_t nArg2, std::intptr_t nArg3);
	static bool _ThreadEventGUIUnlockProc(std::intptr_t nContext, std::intptr_t nArg1, std::intptr_t nArg2, std::intptr_t nArg3);
	static bool _ThreadEventGUIWaitTillNonZeroProc(std::intptr_t nContext, std::intptr_t nArg1, std::intptr_t nArg2, std::intptr_t nArg3);
private:
	std::list<std::pair<MCF::TString, UINT>> _m_lstQueuedMessageBoxes;
	MCF::CriticalSection _m_csMessageBoxQueueLock;

	long _m_lLockCount;
	std::forward_list<const std::intptr_t *>_m_lstWaitingForWhat;

	MCF::TabControlClass _m_TabControl;

	VGAClass _m_VGA;
	KeyboardClass _m_Keyboard;
	BuzzerClass _m_Buzzer;
public:
	MainDialogClass();
	virtual ~MainDialogClass();
protected:
	virtual void _PostSubclass() override;
	virtual void _PreUnsubclass() override;

	virtual bool _IdleLoop() override;
	virtual bool _PreTranslateDialogMessage(MSG *lpMsg) override;

	virtual bool _OnInitDialog(HWND hDefControl, LPARAM lInitParam) override;
	virtual void _OnDestroy() override;
	virtual void _OnClose() override;
	virtual bool _OnCommand(WORD wNotifyCode, int nControlID, HWND hSender) override;
	virtual bool _OnSetCursor(HWND hInWhichWindow, int nHitTestCode, UINT uMsg) override;
	virtual void _OnTimer(UINT_PTR uTimerID, TIMERPROC lpfnTimerProc) override;
private:
	void _Lock();
	void _Unlock();
	void _WaitTillNonZero(const std::intptr_t *lpnVar);

	void _QueueMessageBox(LPCTSTR lpszText, UINT uFlags);
};
